package rs.udd.model;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.hibernate.envers.Audited;
import org.hibernate.validator.constraints.NotBlank;

@Audited
@Entity
@Table(name = "UDD_ADVERTS")
public class Advert extends AbstractEntity {

	private static final long serialVersionUID = -1186537466454222847L;

	@NotBlank
	private String title;

	@NotBlank
	private String abstractText;

	@NotBlank
	private String filePath;

	@NotNull
	@ManyToOne
	@JoinColumn(name = "fkAdvertiser", referencedColumnName = "id")
	private Advertiser advertiser;

	@NotNull
	@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH }, targetEntity = KeyWord.class) // initiates creation of KeyWord
	@JoinTable(name = "UDD_ADVERT_KEY_WORDS",
			joinColumns = { @JoinColumn(name = "fkAdvert", referencedColumnName = "id", nullable = false) },
			inverseJoinColumns = { @JoinColumn(name = "fkKeyWord", referencedColumnName = "id", nullable = false) })
	private Set<KeyWord> keyWords = new HashSet<KeyWord>();

	@NotNull
	@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH }, targetEntity = Category.class)	// initiates adding to Category
	@JoinTable(name = "UDD_CATEGORY_ADVERT",
			joinColumns = { @JoinColumn(name = "fkAdvert", referencedColumnName = "id", nullable = false) },
			inverseJoinColumns = { @JoinColumn(name = "fkCategory", referencedColumnName = "id", nullable = false) })
	private Set<Category> categories = new HashSet<Category>();

	@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "advert")
	private Set<AgentAdvertApplication> applicatedByAgents = new HashSet<AgentAdvertApplication>();

	private String indexedDocumentId;

	public Advert() {

	}

	public Advertiser getAdvertiser() {
		return advertiser;
	}

	public void setAdvertiser(Advertiser advertiser) {
		this.advertiser = advertiser;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getAbstractText() {
		return abstractText;
	}

	public void setAbstractText(String abstractText) {
		this.abstractText = abstractText;
	}

	public Set<KeyWord> getKeyWords() {
		return keyWords;
	}

	public void setKeyWords(Set<KeyWord> keyWords) {
		this.keyWords = keyWords;
	}

	public Set<Category> getCategories() {
		return categories;
	}

	public void setCategories(Set<Category> categories) {
		this.categories = categories;
	}

	public String getFilePath() {
		return filePath;
	}

	public void setFilePath(String filePath) {
		this.filePath = filePath;
	}

	public String getIndexedDocumentId() {
		return indexedDocumentId;
	}

	public void setIndexedDocumentId(String indexedDocumentId) {
		this.indexedDocumentId = indexedDocumentId;
	}

	public Set<AgentAdvertApplication> getApplicatedByAgents() {
		return applicatedByAgents;
	}

	public void setApplicatedByAgents(Set<AgentAdvertApplication> applicatedByAgents) {
		this.applicatedByAgents = applicatedByAgents;
	}

	@Override
	public int hashCode() {

		return new HashCodeBuilder()
				.appendSuper(super.hashCode())
				.append(title)
				.append(abstractText)
				.append(filePath)
				.hashCode();
	}

	@Override
	public boolean equals(Object obj) {

		if (obj == null) {
			return false;
		}
		if (obj == this) {
			return true;
		}
		if (obj.getClass() != getClass()) {
			return false;
		}

		final Advert otherAdvert = (Advert) obj;

		return new EqualsBuilder()
				.appendSuper(super.equals(obj))
				.append(title, otherAdvert.getTitle())
				.append(abstractText, otherAdvert.getAbstractText())
				.append(filePath, otherAdvert.getFilePath())
				.isEquals();
	}

	@Override
	public String toString() {

		return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
				.append(super.toString())
				.append("title", title)
				.append("abstractText", abstractText)
				.append("filePath", filePath)
				.toString();
	}

}
